home *** CD-ROM | disk | FTP | other *** search
- head 1.3;
- branch ;
- access ;
- symbols ;
- locks brent:1.3; strict;
- comment @ * @;
-
-
- 1.3
- date 88.08.26.17.43.37; author brent; state Exp;
- branches ;
- next 1.2;
-
- 1.2
- date 88.08.26.16.23.53; author brent; state Exp;
- branches ;
- next 1.1;
-
- 1.1
- date 88.04.16.12.28.31; author brent; state Exp;
- branches ;
- next ;
-
-
- desc
- @Server code for pseudo-device benchmark
- @
-
-
- 1.3
- log
- @Updated to new, standard, pseudo-device interface
- @
- text
- @/*
- * server.c --
- *
- * The server part of some multi-program synchronization primatives.
- * The routines here control N client programs. This just means
- * telling them all to start, and hearing back from them when they're done.
- *
- * Copyright 1986 Regents of the University of California
- * All rights reserved.
- */
-
- #ifndef lint
- static char rcsid[] = "$Header: server.c,v 1.2 88/08/26 16:23:53 brent Exp $ SPRITE (Berkeley)";
- #endif not lint
-
-
- #include "sprite.h"
- #include "status.h"
- #include "fs.h"
- #include "dev/pdev.h"
- #include "io.h"
- #include "bit.h"
- #include "time.h"
- #include "sys.h"
-
- char *pdev="./pdev.new";
-
- extern Boolean writeBehind;
- extern int delay;
-
- typedef int (*IntProc)();
-
- typedef struct ServerState {
- int cntlStream; /* Control stream to find out new clientStream's */
- int numClients;
- int *clientStream; /* Array of client streams */
- int maxStreamID;
- Address *request; /* Array of client request buffers */
- char *clientState; /* Array of client state words */
- int *selectMask;
- int selectMaskBytes;
- IntProc opTable[7]; /* Operation switch table */
- } ServerState;
-
- #define REQUEST_BUF_SIZE (2048 + sizeof(Pdev_Request))
- #define CLIENT_OPENED 0x1
- #define CLIENT_STARTED 0x2
- #define CLIENT_FINISHED 0x4
-
- /*
- * Need the select flag to know if we should block the client.
- */
- extern Boolean select;
- Boolean blocked = FALSE;
-
- /*
- * Forward Declarations
- */
- ReturnStatus NullProc();
- ReturnStatus ServeOpen();
- ReturnStatus ServeRead();
- ReturnStatus ServeWrite();
- ReturnStatus ServeIOControl();
- Pdev_Op ServeRequest();
-
-
- /*
- *----------------------------------------------------------------------
- *
- * ServerSetup --
- *
- * Establish contact with N clients. A pseudo device is opened
- * and we are declared its "master", or "server". After this
- * other processes can open the pseudo device and we'll get a private
- * stream back that we use for requests from that process.
- *
- * Results:
- * A pointer to state about the clients needed by ServerStart and
- * ServerWait.
- *
- * Side effects:
- * Opens the pseudo device as the server and waits for numClients
- * opens by client processes.
- * This exits (kills the process) upon error.
- *
- *----------------------------------------------------------------------
- */
-
- void
- ServerSetup(numClients, dataPtr)
- int numClients;
- ClientData *dataPtr;
- {
- ServerState *statePtr;
- int client;
- int len;
- int amountRead;
- ReturnStatus status;
- Pdev_Notify notify;
- Pdev_SetBufArgs setBuf;
- int streamID;
- int maxStreamID;
-
- statePtr = (ServerState *)Mem_Alloc(sizeof(ServerState));
- statePtr->clientStream = (int *)Mem_Alloc(numClients * sizeof(int));
- statePtr->clientState = (char *)Mem_Alloc(numClients);
- statePtr->request = (Address *)Mem_Alloc(numClients * sizeof(Address));
- statePtr->numClients = numClients;
-
- statePtr->opTable[(int)PDEV_OPEN] = ServeOpen;
- statePtr->opTable[(int)PDEV_CLOSE] = NullProc;
- statePtr->opTable[(int)PDEV_READ] = ServeRead;
- statePtr->opTable[(int)PDEV_WRITE] = ServeWrite;
- statePtr->opTable[(int)PDEV_IOCTL] = ServeIOControl;
-
- /*
- * Open the pseudo device.
- */
- status = Fs_Open(pdev, FS_READ|FS_CREATE|FS_NEW_MASTER,
- 0666, &statePtr->cntlStream);
- #ifdef notdef
- if (status == FS_FILE_NOT_FOUND) {
- status = Fs_Open(pdev, FS_CREATE|FS_READ|FS_NEW_MASTER,
- 0666, &statePtr->cntlStream);
- }
- #endif
- if (status != SUCCESS) {
- Stat_PrintMsg(status, "Error opening pseudo device as master");
- Proc_Exit(status);
- }
- maxStreamID = 0;
- for (client=0 ; client<numClients ; client++) {
- /*
- * Read on our control stream (the one we just opened) messages
- * that contain new streamIDs. These are for private streams
- * back to the client process..
- */
- len = sizeof(notify);
- status = Fs_Read(statePtr->cntlStream, len, (Address)¬ify,
- &amountRead);
- if (status != SUCCESS) {
- Stat_PrintMsg(status, "Error reading control stream");
- Proc_Exit(status);
- } else if (amountRead != sizeof(notify)) {
- Io_PrintStream(io_StdErr,
- "Warning, short read (%d) on control stream\n", amountRead);
- Io_Flush(io_StdErr);
- }
- streamID = notify.newStreamID;
- if (streamID > statePtr->maxStreamID) {
- statePtr->maxStreamID = streamID;
- }
- /*
- * Tell the kernel where the request buffer is.
- */
- statePtr->request[client] = Mem_Alloc(REQUEST_BUF_SIZE);
- setBuf.requestBufAddr = statePtr->request[client];
- setBuf.requestBufSize = REQUEST_BUF_SIZE;
- setBuf.readBufAddr = (Address)NULL;
- setBuf.readBufSize = 0;
- Fs_IOControl(streamID, IOC_PDEV_SET_BUF,
- sizeof(Pdev_SetBufArgs), (Address)&setBuf, 0, NULL);
- /*
- * Set(Unset) write-behind by the client.
- */
- Fs_IOControl(streamID, IOC_PDEV_WRITE_BEHIND,
- sizeof(int), (Address)&writeBehind, 0, NULL);
- statePtr->clientStream[client] = streamID;
- statePtr->clientState[client] = CLIENT_OPENED;
- Io_PrintStream(io_StdErr, "Got client on stream %d\n",streamID);
- Io_Flush(io_StdErr);
- ServeRequest(statePtr->clientStream[client],
- statePtr->request[client],
- statePtr->opTable);
- }
- Io_Flush(io_StdErr);
- /*
- * Now that we know the largest stream ID used for a client stream
- * we can allocate and initialize the select mask for the streams.
- */
- statePtr->selectMaskBytes = Bit_NumBytes(statePtr->maxStreamID);
- statePtr->selectMask = (int *)Mem_Alloc(statePtr->selectMaskBytes);
- Byte_Zero(statePtr->selectMaskBytes, (Address)statePtr->selectMask);
- for (client=0 ; client < numClients ; client++) {
- Bit_Set(statePtr->clientStream[client], statePtr->selectMask);
- }
- *dataPtr = (ClientData)statePtr;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * ServeRequest --
- *
- * The top level service routine that reads client requests
- * and branches out to a handler for the request. This takes
- * care of error conditions and allocating space for the
- * request and the reply parameters.
- *
- * Results:
- * None
- *
- * Side effects:
- * The server side of the pseudo-device protocol.
- *
- *----------------------------------------------------------------------
- */
-
- Pdev_Op
- ServeRequest(clientStreamID, myRequestBuf, opTable)
- int clientStreamID;
- Address myRequestBuf;
- IntProc *opTable;
- {
- register ReturnStatus status;
- register Pdev_Request *requestPtr;
- Pdev_Reply reply;
- Pdev_BufPtrs bufPtrs;
- register Pdev_Op operation;
- int numBytes;
- char replyBuf[REQUEST_BUF_SIZE];
- register char *requestData;
- register Address requestBuf;
- register int i;
-
- /*
- * Read the current pointers for the request buffer.
- */
-
- status = Fs_Read(clientStreamID, sizeof(Pdev_BufPtrs),
- (Address) &bufPtrs, &numBytes);
- if ((status != SUCCESS) || (numBytes != sizeof(Pdev_BufPtrs))) {
- Sys_Panic(SYS_FATAL, "%s; status \"%s\", count %d",
- "ServeRequest had trouble reading request buffer pointers",
- Stat_GetMsg(status), numBytes);
- }
- if (bufPtrs.magic != PDEV_BUF_PTR_MAGIC) {
- Sys_Panic(SYS_FATAL, "%s: %d",
- "ServeRequest got bad pointer magic number",
- bufPtrs.magic);
- }
- /*
- * While there are still requests in the buffer, service them.
- */
- requestBuf = bufPtrs.requestAddr;
- while (bufPtrs.requestFirstByte < bufPtrs.requestLastByte) {
- requestPtr = (Pdev_Request *)&requestBuf[bufPtrs.requestFirstByte];
- if (requestPtr->magic != PDEV_REQUEST_MAGIC) {
- Sys_Panic(SYS_FATAL, "ServeRequest, bad request magic # 0x%x\n",
- requestPtr->magic);
- }
- requestData = (Address)((int)requestPtr + sizeof(Pdev_Request));
-
- /*
- * Switch out the to the handler for the pdev operation.
- */
- operation = requestPtr->operation;
- status = (*opTable[(int)operation])(clientStreamID,
- requestPtr, requestData, replyBuf, &reply.selectBits);
-
- if (delay > 0) {
- for (i=delay<<1 ; i>0 ; i--) ;
- }
-
- if (!writeBehind || operation != PDEV_WRITE) {
- /*
- * Set up the reply and tell the kernel about it.
- */
-
- reply.magic = PDEV_REPLY_MAGIC;
- reply.status = SUCCESS;
- reply.replySize = requestPtr->replySize;
- reply.replyBuf = replyBuf;
- status = Fs_IOControl(clientStreamID, IOC_PDEV_REPLY,
- sizeof(Pdev_Reply),
- (Address) &reply, 0, NULL);
- if (status != SUCCESS) {
- Sys_Panic(SYS_FATAL, "%s; status \"%s\"",
- "ServeRequest couldn't send reply",
- Stat_GetMsg(status));
- }
- }
- bufPtrs.requestFirstByte += requestPtr->messageSize;
- }
- Fs_IOControl(clientStreamID, IOC_PDEV_SET_PTRS,
- sizeof(Pdev_BufPtrs), (Address)&bufPtrs,
- 0, NULL);
- return(operation);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Serve --
- *
- * Listen for requests from client's, returning after all clients
- * have closed their streams.
- *
- * Results:
- * None
- *
- * Side effects:
- * Handle all requests by clients.
- *
- *----------------------------------------------------------------------
- */
-
- void
- Serve(data)
- ClientData data;
- {
- ServerState *statePtr;
- int client;
- ReturnStatus status;
- int *selectMask;
- int numFinishedClients;
- int numReady;
- Pdev_Op operation;
-
- statePtr = (ServerState *)data;
- selectMask = (int *)Mem_Alloc(statePtr->selectMaskBytes);
- numFinishedClients = 0;
- do {
- Byte_Copy(statePtr->selectMaskBytes, (Address)statePtr->selectMask,
- (Address)selectMask);
- status = Fs_Select(statePtr->numClients, NULL, selectMask,
- NULL, NULL, &numReady);
- for (client=0 ; client < statePtr->numClients ; client++) {
- /*
- * Look for the each client's bit in the select mask and read the
- * corresponding stream for its initial request.
- */
- if (Bit_IsSet(statePtr->clientStream[client], selectMask)) {
- /*
- * Handle the client's request. If it's a close
- * then clear the client's bit from the select mask so
- * don't bother checking it again.
- */
- operation = ServeRequest(statePtr->clientStream[client],
- statePtr->request[client],
- statePtr->opTable);
- if (operation == PDEV_CLOSE ||
- operation == (Pdev_Op)-1) {
- Io_PrintStream(io_StdErr, "Client %d %s...", client,
- (operation == PDEV_CLOSE) ? "closed" : "error" );
- Io_Flush(io_StdErr);
- numFinishedClients++;
- statePtr->clientState[client] |= CLIENT_FINISHED;
- Bit_Clear(statePtr->clientStream[client],
- statePtr->selectMask);
- } else if ((operation == PDEV_READ) && select) {
- /*
- * If the select flag is set, then we must
- * remember to simulate input for the client
- * every so often. This tests regular blocking
- * reads, and selects by the client. This goes
- * with the fact that we only return FS_WRITABLE
- * if the select flag is set.
- */
- Time time;
- int selectBits;
- time.seconds = 0;
- time.microseconds = 400;
- Sync_WaitTime(time);
- Io_Print("Waking up client\n"); Io_Flush(io_StdOut);
- selectBits = FS_READABLE|FS_WRITABLE;
- Fs_IOControl(statePtr->clientStream[client],
- IOC_PDEV_READY, sizeof(int), &selectBits,
- 0, NULL);
- }
- }
- }
- } while (numFinishedClients < statePtr->numClients);
- Io_PrintStream(io_StdErr, "\n");
- Io_Flush(io_StdErr);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * ServeOne --
- *
- * A service loop for one client. More bare-bones test used
- * for timing.
- *
- * Results:
- * None
- *
- * Side effects:
- * Handle all requests one client.
- *
- *----------------------------------------------------------------------
- */
-
- void
- ServeOne(data)
- ClientData data;
- {
- register ServerState *statePtr;
- register int client;
- ReturnStatus status;
- int *selectMask;
- int numFinishedClients;
- int numReady;
- Pdev_Op operation;
-
- statePtr = (ServerState *)data;
- client = 0;
- do {
- operation = ServeRequest(statePtr->clientStream[client],
- statePtr->request[client],
- statePtr->opTable);
- if (operation == PDEV_CLOSE ||
- operation == (Pdev_Op)-1) {
- Io_PrintStream(io_StdErr, "Client %d %s...", client,
- (operation == PDEV_CLOSE) ? "closed" : "error" );
- Io_Flush(io_StdErr);
- break;
- } else if ((operation == PDEV_READ) && select) {
- /*
- * If the select flag is set, then we must
- * remember to simulate input for the client
- * every so often. This tests regular blocking
- * reads, and selects by the client. This goes
- * with the fact that we only return FS_WRITABLE
- * if the select flag is set.
- */
- Time time;
- int selectBits;
- time.seconds = 0;
- time.microseconds = 400;
- Sync_WaitTime(time);
- Io_Print("Waking up client\n"); Io_Flush(io_StdOut);
- selectBits = FS_READABLE|FS_WRITABLE;
- Fs_IOControl(statePtr->clientStream[client],
- IOC_PDEV_READY, sizeof(int), &selectBits,
- 0, NULL);
- }
- } while (1);
- Io_PrintStream(io_StdErr, "\n");
- Io_Flush(io_StdErr);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NullProc --
- *
- * The do-nothing service procedure.
- *
- * Results:
- * SUCCESS
- *
- * Side effects:
- * Zeroes out the reply buffer.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- NullProc(streamID, requestPtr, requestBuf, replyBuf, selectBitsPtr)
- int streamID;
- Pdev_Request *requestPtr;
- Address requestBuf;
- Address replyBuf;
- int *selectBitsPtr;
- {
- if (requestPtr->replySize > 0) {
- Byte_Zero(requestPtr->replySize, replyBuf);
- }
- return(SUCCESS);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * ServeOpen --
- *
- * React to an Open request. This initializes the
- * select state to both readable and writable.
- *
- * Results:
- * SUCCESS
- *
- * Side effects:
- * Print statement.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- ServeOpen(streamID, requestPtr, requestBuf, replyBuf, selectBitsPtr)
- int streamID;
- Pdev_Request *requestPtr;
- Address requestBuf;
- Address replyBuf;
- int *selectBitsPtr;
- {
- Io_PrintStream(io_StdErr, "Open request, streamID %d\n", streamID);
- Io_Flush(io_StdErr);
- *selectBitsPtr = FS_READABLE | FS_WRITABLE;
- return(SUCCESS);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * ServeRead --
- *
- * Return data for a read request. This plays a game with the
- * client if the select flag (-s) is set: every other read
- * gets blocked in order to test IOC_PDEV_READY.
- *
- * Results:
- * SUCCESS
- *
- * Side effects:
- * Zeroes out the reply buffer.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- ServeRead(streamID, requestPtr, requestBuf, replyBuf, selectBitsPtr)
- int streamID;
- Pdev_Request *requestPtr;
- Address requestBuf;
- Address replyBuf;
- int *selectBitsPtr;
- {
- if (select && !blocked) {
- blocked = TRUE;
- *selectBitsPtr = FS_WRITABLE;
- return(FS_WOULD_BLOCK);
- } else {
- if (requestPtr->replySize > 0) {
- Byte_Zero(requestPtr->replySize, replyBuf);
- replyBuf[0] = 'z';
- }
- blocked = FALSE;
- if (! select) {
- *selectBitsPtr = FS_WRITABLE | FS_READABLE;
- } else {
- *selectBitsPtr = FS_WRITABLE;
- }
- return(SUCCESS);
- }
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * ServeWrite --
- *
- * Handle a write request.
- *
- * Results:
- * SUCCESS
- *
- * Side effects:
- * Sets up the select bits.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- ServeWrite(streamID, requestPtr, requestBuf, replyBuf, selectBitsPtr)
- int streamID;
- Pdev_Request *requestPtr;
- Address requestBuf;
- Address replyBuf;
- int *selectBitsPtr;
- {
- *selectBitsPtr = FS_WRITABLE;
- if (! select) {
- *selectBitsPtr |= FS_READABLE;
- }
- requestPtr->replySize = 0;
- return(SUCCESS);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * ServeIOControl --
- *
- * Handle an IOControl. This acts like an echo now.
- *
- * Results:
- * SUCCESS
- *
- * Side effects:
- * Copies the request buffer to the reply buffer.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- ServeIOControl(streamID, requestPtr, requestBuf, replyBuf, selectBitsPtr)
- int streamID;
- Pdev_Request *requestPtr;
- Address requestBuf;
- Address replyBuf;
- int *selectBitsPtr;
- {
- #ifdef notdef
- if (requestPtr->replySize <= requestPtr->requestSize) {
- Byte_Copy(requestPtr->replySize, requestBuf, replyBuf);
- } else {
- Byte_Copy(requestPtr->requestSize, requestBuf, replyBuf);
- Byte_Zero(requestPtr->replySize - requestPtr->requestSize,
- replyBuf[requestPtr->requestSize]);
- }
- #endif
- switch (requestPtr->param.ioctl.command) {
- case IOC_PDEV_SET_BUF: {
- /*
- * Let the client trigger our test of the mid-flight
- * setbuf call.
- */
- Pdev_SetBufArgs setBuf;
-
- setBuf.requestBufAddr = Mem_Alloc(REQUEST_BUF_SIZE);
- setBuf.requestBufSize = REQUEST_BUF_SIZE;
- setBuf.readBufAddr = (Address)NULL;
- setBuf.readBufSize = 0;
- Fs_IOControl(streamID, IOC_PDEV_SET_BUF,
- sizeof(Pdev_SetBufArgs), (Address)&setBuf, 0, NULL);
-
- }
- }
- *selectBitsPtr = FS_WRITABLE;
- if (! select) {
- *selectBitsPtr |= FS_READABLE;
- }
- return(SUCCESS);
- }
- @
-
-
- 1.2
- log
- @Increased buffer size, added delay
- @
- text
- @d13 1
- a13 1
- static char rcsid[] = "$Header: server.c,v 1.1 88/04/16 12:28:31 brent Exp $ SPRITE (Berkeley)";
- d45 1
- a45 1
- #define REQUEST_BUF_SIZE (2048 + sizeof(Pdev_NewRequest))
- a54 1
- Pdev_WaitInfo waitInfo;
- d210 1
- a210 1
- ServeRequest(clientStreamID, requestBuf, opTable)
- d212 1
- a212 1
- Address requestBuf;
- d216 2
- a217 2
- register Pdev_NewRequest *requestPtr;
- Pdev_NewReply reply;
- d247 1
- a247 1
- requestPtr = (Pdev_NewRequest *)&requestBuf[bufPtrs.requestFirstByte];
- d252 1
- a252 1
- requestData = (Address)((int)requestPtr + sizeof(Pdev_NewRequest));
- d275 1
- a275 1
- sizeof(Pdev_NewReply),
- d463 1
- a463 1
- Pdev_NewRequest *requestPtr;
- d494 1
- a494 1
- Pdev_NewRequest *requestPtr;
- d499 1
- a499 2
- Io_PrintStream(io_StdErr, "Open request, streamID %d, clientID %d\n",
- streamID, requestPtr->param.open.clientID);
- d526 1
- a526 1
- Pdev_NewRequest *requestPtr;
- d569 1
- a569 1
- Pdev_NewRequest *requestPtr;
- d601 1
- a601 1
- Pdev_NewRequest *requestPtr;
- @
-
-
- 1.1
- log
- @Initial revision
- @
- text
- @d13 1
- a13 1
- static char rcsid[] = "$Header: server.c,v 1.3 87/06/12 15:03:41 brent Exp $ SPRITE (Berkeley)";
- d29 1
- d45 1
- a45 1
- #define REQUEST_BUF_SIZE 2048
- d225 1
- d261 4
- @
-